package com.gitee.ixtf.rsocket.agent

import com.gitee.ixtf.core.J
import com.gitee.ixtf.guice.Jguice
import com.gitee.ixtf.guice.kotlinx.get
import com.gitee.ixtf.rsocket.BrokerAuth
import com.gitee.ixtf.rsocket.IBrokerServiceAgent
import com.gitee.ixtf.rsocket.broker.SetupRequest
import com.gitee.ixtf.rsocket.service.GetBrokerServiceResponse
import com.gitee.ixtf.rsocket.service.ListBrokerServiceRequest
import io.cloudevents.core.builder.CloudEventBuilder
import io.rsocket.Payload
import io.rsocket.RSocket
import io.vertx.ext.auth.authentication.Credentials
import io.vertx.ext.auth.authentication.TokenCredentials
import io.vertx.ext.auth.jwt.JWTAuth
import io.vertx.kotlin.core.json.jsonObjectOf
import io.vertx.kotlin.ext.auth.jwtOptionsOf
import java.net.URI
import kotlinx.coroutines.reactor.mono
import reactor.core.publisher.Mono

abstract class BrokerServiceAgent : BrokerClientAgent(), IBrokerServiceAgent {
  protected abstract val service: String
  protected open val id: String = J.objectId()

  override suspend fun cloudEventBuilder(): CloudEventBuilder =
      CloudEventBuilder.v1().withId(J.objectId()).withSource(URI("$service:$id"))

  override fun serviceRSocket(serviceRSocket: RSocket) {
    this.serviceRSocket = serviceRSocket
  }

  override fun buildSetupRequest(): Mono<Payload> = mono {
    SetupRequest.service(service, buildCredentials(), id)
  }

  override suspend fun buildCredentials(): Credentials {
    val claims = jsonObjectOf("sub" to service)
    val options = jwtOptionsOf(expiresInMinutes = 5)
    val token = Jguice.get<JWTAuth>(BrokerAuth::class.java).generateToken(claims, options)
    return TokenCredentials(token)
  }

  override suspend fun listBrokerService(
      request: ListBrokerServiceRequest
  ): Collection<GetBrokerServiceResponse> {
    TODO("Not yet implemented")
  }
}
